/**
 * @file    iypower_rs485.c
 * @brief   逆变器协议-爱阳逆变器-RS485协议
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-09-04
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-09-04 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "iypower_rs485.h"
#include "modbus_app.h"
#include "if_di.h"
#include "cfg_prj.h"
#include "sample.h"
#include "parallel_com.h"
#include "var_mng.h"
#include "param_mng.h"
/* macro/define --------------------------------------------------------------*/
#define INTPUT_REG_SIZE      (0x74)
#define CMD_READ_IN_REG      (0x03)
/* typedef -------------------------------------------------------------------*/
// 系统状态
typedef union 
{
	uint16_t data;
	struct 
	{
		uint16_t state :2;
		uint16_t err_flag:1;
		uint16_t blc_state:1;
		uint16_t sleep_state:1;
		uint16_t dsg_out_state:1;
		uint16_t chg_in_state:1;
		uint16_t link_state:1;
		
		uint16_t mode:2;
		uint16_t sp_state:2;
		uint16_t force_chg:1;
	}bit_name;
}system_state_type;

// 保护信息 
typedef union 
{
    uint16_t data;
	struct 
	{
		uint16_t cov :1;
		uint16_t cuv :1;
		uint16_t oc :1;
		uint16_t sc :1;
		uint16_t ot :1;
		uint16_t ut :1;
		uint16_t vdiff:1;
		uint16_t sys_err:1;
		uint16_t soft_reset:1;
	}bit_name;
}prp_msg_type;

// 告警信息
typedef union 
{
    uint16_t data;
	struct 
	{
		uint16_t cov :1;
		uint16_t cuv :1;
		uint16_t oc :1;
		uint16_t ot :1;
		uint16_t ut :1;
		uint16_t vdiff :1;
	}bit_name;
}alm_msg_type;
/* local functions -----------------------------------------------------------*/
static void iypower_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void iypower_update_slave_msg(uint8_t slave_addr);
static uint16_t iypower_get_slave_state(uint8_t slave_addr);
static uint16_t iypower_get_slave_alm_msg(uint8_t slave_addr);
static uint16_t iypower_get_slave_prp_msg(uint8_t slave_addr);
static uint16_t iypower_get_master_state(void);
static uint16_t iypower_get_master_alm_msg(void);
static uint16_t iypower_get_master_prp_msg(void);
static void iypower_update_total_msg(void);
/* static variables ----------------------------------------------------------*/
static uint16_t input_reg_buf[INTPUT_REG_SIZE] = {0};

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
uint8_t iypower_rs485_analysis(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len)
{
    md_data_type recv_md_data = {0};
    if(TRUE == modbus_rtu_analysis(rx_buf , rx_len , &recv_md_data))
    {
		if(recv_md_data.addr == var_get_data(VAR_ID_SELF_ADDR))
		{
			if((recv_md_data.addr == 0) || (recv_md_data.addr == 1))
			{
				if((recv_md_data.reg_addr + recv_md_data.data_len <= INTPUT_REG_SIZE)
				  &&(CMD_READ_IN_REG == recv_md_data.cmd_code))
				{
					iypower_update_total_msg();
					iypower_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
				}
				return FALSE;
			}
			else
			{
				if((recv_md_data.reg_addr + recv_md_data.data_len <= INTPUT_REG_SIZE)
				  &&(CMD_READ_IN_REG == recv_md_data.cmd_code))
				{
					iypower_update_slave_msg(recv_md_data.addr);
					iypower_read_input_reg(recv_md_data , tx_buf , tx_len);
					return TRUE;
				}
				return FALSE;
			}
			//return FALSE;
		}
//		else
//		{
//		/*	if(recv_md_data.addr == (var_get_data(VAR_ID_SELF_ADDR) + 1))
//			{
//				if((recv_md_data.reg_addr + recv_md_data.data_len <= INTPUT_REG_SIZE)
//				  &&(CMD_READ_IN_REG == recv_md_data.cmd_code))
//				{
//					iypower_update_slave_msg(recv_md_data.addr);
//					iypower_read_input_reg(recv_md_data , tx_buf , tx_len);
//					return TRUE;
//				}
//				return FALSE;
//			}
//			else
//			{
//				return FALSE;
//			} */
//			return FALSE;
//		}
		 return FALSE;
    }
    return FALSE;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void iypower_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;

    *p_tx ++ = md_data_msg.addr;
    *p_tx ++ = md_data_msg.cmd_code;
    data_len = md_data_msg.data_len * 2; 
    *p_tx ++ = data_len;
    
    for(i = 0;i < md_data_msg.data_len; ++ i)
    {
        *p_tx ++ = input_reg_buf[i + md_data_msg.reg_addr] >> 8;
        *p_tx ++  = input_reg_buf[i + md_data_msg.reg_addr] & 0xff;
    }

    crc_code = modbus_calc_crc(tx_buf , data_len + 3);

    *p_tx ++ = crc_code;
    *p_tx ++ = crc_code >> 8;

    *tx_len = (data_len + 5);
} 

static void iypower_update_slave_msg(uint8_t slave_addr)
{
    uint8_t i = 0;
	uint16_t chg_time = 0;
	int16_t v16_val = 0;
	int32_t v32_val=0;
	uint8_t max_volt_sn = 0;
	uint8_t min_volt_sn = 0;
	uint16_t max_volt_val = 0;
	uint16_t min_volt_val = 0;
	uint8_t max_temp_sn = 0;
	uint8_t min_temp_sn = 0;
	int16_t max_temp_val = 0;
	int16_t min_temp_val = 0;
	if(slave_addr == 0)
		slave_addr = 1;
	else
		slave_addr = slave_addr - 1;
	
	input_reg_buf[0] = 0;
    for(i = 0;i < 8; ++ i)
    {
        input_reg_buf[i + 1] = LIT_TO_BIG(master_data_reg.slave_data[slave_addr].sn_code[i]);
    }
    input_reg_buf[0x10] = 0x00;
    input_reg_buf[0x11] = (SOFT_VER_MAIN << 8) + SOFT_VER_RELEASE;
    input_reg_buf[0x12] = 0x00;
    input_reg_buf[0x13] = 0x00;
	input_reg_buf[0x1C] = 0x4356;
    input_reg_buf[0x1D] = 0x5445;
    input_reg_buf[0x1E] = 0x5F43;
	input_reg_buf[0x1F] = 0x4F4D;  //识别码

    input_reg_buf[0x20] = iypower_get_slave_state(slave_addr);
    input_reg_buf[0x21] = master_data_reg.slave_data[slave_addr].batt_volt;
	v32_val = master_data_reg.slave_data[slave_addr].curr_h16 + master_data_reg.slave_data[slave_addr].curr_l16;
	if(master_data_reg.slave_data[i].curr_h16 & 0x8000)
	{
		v16_val = -(~v32_val + 1);
	}
	else
	{
		v16_val = v32_val;
	}
    input_reg_buf[0x22] = v16_val;
    input_reg_buf[0x23] = master_data_reg.slave_data[slave_addr].max_temp*0.1-273;
    input_reg_buf[0x24] = master_data_reg.slave_data[slave_addr].soc;
	input_reg_buf[0x25] = master_data_reg.slave_data[slave_addr].real_cap;
	input_reg_buf[0x26] = master_data_reg.slave_data[slave_addr].full_cap;
	input_reg_buf[0x27] = iypower_get_slave_prp_msg(slave_addr);
	input_reg_buf[0x28] = iypower_get_slave_alm_msg(slave_addr);
	input_reg_buf[0x29] = master_data_reg.slave_data[slave_addr].sop_cc*10;
	input_reg_buf[0x2A] = var_get_data(VAR_ID_SOP_CV)*10;
	input_reg_buf[0x2B] = master_data_reg.slave_data[slave_addr].soc;
	input_reg_buf[0x2C] = master_data_reg.slave_data[slave_addr].cycle;
	// 充电剩余时间 
	if(v16_val > 0)
	{
		chg_time = 1.0*(100-master_data_reg.slave_data[slave_addr].soc)*master_data_reg.slave_data[slave_addr].full_cap/v16_val*60;
	}
	else
	{
		chg_time = 0xffff;
	}
	input_reg_buf[0x2D] = chg_time;
	max_volt_sn = 1;
	min_volt_sn = 1;
	max_volt_val = 0;
	min_volt_val = 0xffff;
	for(i =0 ;(i < master_data_reg.cell_num) && (i < SLAVE_CELL_NUM); ++ i)
	{
		if(master_data_reg.slave_data[slave_addr].cell_volt_buf[i] > max_volt_val)
		{
			max_volt_val = master_data_reg.slave_data[slave_addr].cell_volt_buf[i];
			max_volt_sn = i;
		}
		
		if(master_data_reg.slave_data[slave_addr].cell_volt_buf[i] < min_volt_val)
		{
			min_volt_val = master_data_reg.slave_data[slave_addr].cell_volt_buf[i];
			min_volt_sn = i;
		}
	}
	
	max_temp_sn = 1;
	min_temp_sn = 1;
	max_temp_val = 0;
	min_temp_val = 120;
	for(i =0 ;(i < master_data_reg.temp_num) && (i < SLAVE_TEMP_NUM); ++ i)
	{
		v16_val = master_data_reg.slave_data[slave_addr].cell_temp_buf[i]*0.1 - 273;
		if(v16_val > max_temp_val)
		{
			max_temp_val = v16_val;
			max_temp_sn = i;
		}
		
		if(v16_val < min_temp_val)
		{
			min_temp_val = v16_val;
			min_temp_sn = i;
		}
	}

	input_reg_buf[0x2E] = max_volt_val;
	input_reg_buf[0x2F] = max_volt_sn;
	input_reg_buf[0x30] = min_volt_val;
	input_reg_buf[0x31] = min_volt_sn;
	input_reg_buf[0x32] = max_volt_val-min_volt_val;
	input_reg_buf[0x33] = max_temp_val;
	input_reg_buf[0x34] = max_temp_sn;
	input_reg_buf[0x35] = min_temp_val;
	input_reg_buf[0x36] = min_temp_sn;
	
	input_reg_buf[0x40] = master_data_reg.cell_num;
	for(i=0;(i<master_data_reg.cell_num) && (i < SLAVE_CELL_NUM);++i)
	{
		input_reg_buf[0x40+i] = master_data_reg.slave_data[slave_addr].cell_volt_buf[i];
	}
	for(;i<26;++i)
	{
		input_reg_buf[0x40+i]=0;
	}
	
	input_reg_buf[0x64] = master_data_reg.slave_data[slave_addr].env_temp*0.1-273;
	input_reg_buf[0x64] = master_data_reg.slave_data[slave_addr].mos_temp*0.1-273;
	input_reg_buf[0x64] = 0;
	input_reg_buf[0x64] = 0;
	input_reg_buf[0x64] = master_data_reg.temp_num;
	
	for(i=0;(i<SLAVE_TEMP_NUM)&&(i<master_data_reg.temp_num);++i)
	{
		input_reg_buf[0x65+i] = master_data_reg.slave_data[slave_addr].cell_temp_buf[i]*0.1-273;
	}
	
	for(;i<10;++i)
	{
		input_reg_buf[0x64+i] = 0;
	}
}

static void iypower_update_total_msg(void)
{
	int16_t sys_curr = 0;
    uint8_t i = 0;
	uint16_t chg_time = 0;
	uint8_t temp_num = 0;
	uint16_t cap_val = 0;
    for(i = 0;i < 15; ++ i)
    {
        input_reg_buf[i] = param_get_data(PAR_ID_SN_CODE + i);
    }
	
    input_reg_buf[0x10] = 0x00;
    input_reg_buf[0x11] = (SOFT_VER_MAIN << 8) + SOFT_VER_RELEASE;
    input_reg_buf[0x12] = 0x00;
    input_reg_buf[0x13] = 0x00;
	input_reg_buf[0x1C] = 0x4356;
    input_reg_buf[0x1D] = 0x5445;
    input_reg_buf[0x1E] = 0x5F43;
	input_reg_buf[0x1F] = 0x4F4D;

    input_reg_buf[0x20] = iypower_get_master_state();
    input_reg_buf[0x21] = master_data_reg.avg_batt_volt;
    sys_curr = master_data_reg.total_bus_curr;
    input_reg_buf[0x22] = sys_curr;
    input_reg_buf[0x23] = master_data_reg.max_temp_val*0.1-273;
    input_reg_buf[0x24] = master_data_reg.avg_soc;
	
	cap_val = master_data_reg.total_real_cap;
	if(master_data_reg.total_real_cap >= MAX_DISP_CAP)
		cap_val = MAX_DISP_CAP;
	input_reg_buf[0x25] = cap_val;
	
	cap_val = master_data_reg.total_full_cap;
	if(master_data_reg.total_full_cap >= MAX_DISP_CAP)
		cap_val = MAX_DISP_CAP;
	input_reg_buf[0x26] = cap_val;
	
	input_reg_buf[0x27] = iypower_get_master_prp_msg();
	input_reg_buf[0x28] = iypower_get_master_alm_msg();
	input_reg_buf[0x29] = var_get_data(VAR_ID_TP_SOP_CC)*10;
	input_reg_buf[0x2A] = var_get_data(VAR_ID_TP_SOP_CV)*10;
	input_reg_buf[0x2B] = master_data_reg.avg_soh;
	input_reg_buf[0x2C] = master_data_reg.avg_cycle;
	// 充电剩余时间 
	if(master_data_reg.total_bus_curr > 0)
	{
		chg_time = (100-master_data_reg.avg_soc)*master_data_reg.total_full_cap*0.01/master_data_reg.total_bus_curr*60;
	}
	else
	{
		chg_time = 0xffff;
	}
	input_reg_buf[0x2D] = chg_time;
	input_reg_buf[0x2E] = master_data_reg.avg_max_volt;
	input_reg_buf[0x2F] = master_data_reg.max_volt_sn;
	input_reg_buf[0x30] = master_data_reg.avg_min_volt;
	input_reg_buf[0x31] = master_data_reg.min_volt_sn;
	input_reg_buf[0x32] = master_data_reg.avg_max_volt-master_data_reg.avg_min_volt;
	input_reg_buf[0x33] = master_data_reg.max_temp_val*0.1-273;
	input_reg_buf[0x34] = 1;
	input_reg_buf[0x35] = master_data_reg.min_temp_val*0.1-273;
	input_reg_buf[0x36] = 1;
	
	input_reg_buf[0x40] = param_get_data(PAR_ID_CB_CELL_NUM);
	for(i=0;i< input_reg_buf[0x40] ;++i)
	{
		input_reg_buf[0x40+i] = master_data_reg.avg_cell_buf[i];
	}
	for(;i<26;++i)
	{
		input_reg_buf[0x40+i]=0;
	}
	
	input_reg_buf[0x60] = var_get_data(VAR_ID_ENV_TEMP)*0.1-273;
	input_reg_buf[0x61] = var_get_data(VAR_ID_MOS_TEMP)*0.1-273;
	input_reg_buf[0x62] = 0;
	input_reg_buf[0x63] = 0;
	
	temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;
	
	input_reg_buf[0x64] = temp_num;
	for(i=0;i<temp_num;++i)
	{
		input_reg_buf[0x64+i]=master_data_reg.avg_temp_buf[i]*0.1-273;
	}
	for(;i<10;++i)
	{
		input_reg_buf[0x64+i]=0;
	}
}

static uint16_t iypower_get_slave_state(uint8_t slave_addr)
{
	system_state_type sys_state = {0};
	int32_t sys_curr = 0;
	
	if(slave_addr >= CFG_PARALLEL_NUM)
		return 0;

	sys_curr = master_data_reg.slave_data[slave_addr].curr_h16 + master_data_reg.slave_data[slave_addr].curr_l16;
	if(sys_curr > 0)
		sys_state.bit_name.state = 0x02;
	else if(sys_curr < 0)
		sys_state.bit_name.state = 0x03;
	else
		sys_state.bit_name.state = 0x01;
	
    sys_state.bit_name.mode = 0x00;
    sys_state.bit_name.blc_state = 0;
    
    if(master_data_reg.slave_data[slave_addr].sop_dc > 0)
        sys_state.bit_name.dsg_out_state = 1;
    else
        sys_state.bit_name.dsg_out_state = 0;
    
    if(master_data_reg.slave_data[slave_addr].sop_cc > 0)
        sys_state.bit_name.chg_in_state = 1;
    else
        sys_state.bit_name.chg_in_state = 0;

	return sys_state.data;
}

static uint16_t iypower_get_slave_prp_msg(uint8_t slave_addr)
{
	prp_msg_type prp_msg = {0};
	
	if(slave_addr >= CFG_PARALLEL_NUM)
		return 0;

    prp_msg.bit_name.cov = master_data_reg.slave_data[slave_addr].prp_volt_status.name.cov;
    prp_msg.bit_name.cuv = master_data_reg.slave_data[slave_addr].prp_volt_status.name.cuv;
    prp_msg.bit_name.oc = master_data_reg.slave_data[slave_addr].prp_volt_status.name.ocd  
	                       | master_data_reg.slave_data[slave_addr].prp_volt_status.name.occ 
						   | master_data_reg.slave_data[slave_addr].prp_volt_status.name.ocd2;
    prp_msg.bit_name.sc = master_data_reg.slave_data[slave_addr].prp_volt_status.name.sc;
    prp_msg.bit_name.ot = master_data_reg.slave_data[slave_addr].prp_temp_status.name.otc
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.otd
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.otm
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.ote;
    prp_msg.bit_name.ot = master_data_reg.slave_data[slave_addr].prp_temp_status.name.utc
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.utd
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.ute;
    prp_msg.bit_name.vdiff = master_data_reg.slave_data[slave_addr].prp_volt_status.name.vdiff;
    prp_msg.bit_name.sys_err = master_data_reg.slave_data[slave_addr].prp_temp_status.name.cmos_ft
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.dmos_ft
	                       | master_data_reg.slave_data[slave_addr].prp_volt_status.name.col
						   | master_data_reg.slave_data[slave_addr].prp_temp_status.name.tol;
	
	return prp_msg.data;
}

static uint16_t  iypower_get_slave_alm_msg(uint8_t slave_addr)
{
	alm_msg_type alm_msg = {0};
	
    alm_msg.bit_name.cov = diag_get_alarm(ALM_ID_COV);
    alm_msg.bit_name.cuv = diag_get_alarm(ALM_ID_CUV);
    alm_msg.bit_name.oc = diag_get_alarm(ALM_ID_OCC)|diag_get_alarm(ALM_ID_OCD);
    alm_msg.bit_name.ot = diag_get_alarm(ALM_ID_OTE)|diag_get_alarm(ALM_ID_OTD)|diag_get_alarm(ALM_ID_OTC)|diag_get_alarm(ALM_ID_OTM);
    alm_msg.bit_name.ut = diag_get_alarm(ALM_ID_UTE)|diag_get_alarm(ALM_ID_UTD)|diag_get_alarm(ALM_ID_UTC);
    alm_msg.bit_name.vdiff = diag_get_alarm(ALM_ID_VDIFF);

	alm_msg.data = 0;
	
	return alm_msg.data;
}

static uint16_t iypower_get_master_state(void)
{
    system_state_type sys_state = {0};
	
	if(master_data_reg.total_bus_curr > 0)
		sys_state.bit_name.state = 0x02;
	else if(master_data_reg.total_bus_curr < 0)
		sys_state.bit_name.state = 0x03;
	else
		sys_state.bit_name.state = 0x01;
	
    if (master_data_reg.parallel_num > 1)
    {
        sys_state.bit_name.mode = 0x01;
    }
    else
    {
        sys_state.bit_name.mode = 0x00;
    }

    sys_state.bit_name.blc_state = 0;
    
    if(var_get_data(VAR_ID_TP_SOP_DC) > 0)
        sys_state.bit_name.dsg_out_state = 1;
    else
        sys_state.bit_name.dsg_out_state = 0;
    
    if(var_get_data(VAR_ID_TP_SOP_CC) > 0)
        sys_state.bit_name.chg_in_state = 1;
    else
        sys_state.bit_name.chg_in_state = 0;

	return sys_state.data;
}

static uint16_t iypower_get_master_alm_msg(void)
{
    return 0;
}

static uint16_t iypower_get_master_prp_msg(void)
{
    prp_msg_type prp_msg = {0};
	
    prp_msg.bit_name.cov = master_data_reg.total_prp_msg.bit.cov;
    prp_msg.bit_name.cuv = master_data_reg.total_prp_msg.bit.cuv;
    prp_msg.bit_name.oc = master_data_reg.total_prp_msg.bit.occ|master_data_reg.total_prp_msg.bit.ocd|master_data_reg.total_prp_msg.bit.ocd2;
    prp_msg.bit_name.sc = master_data_reg.total_prp_msg.bit.sc;
    prp_msg.bit_name.ot = master_data_reg.total_prp_msg.bit.otc|master_data_reg.total_prp_msg.bit.otd|master_data_reg.total_prp_msg.bit.otm|master_data_reg.total_prp_msg.bit.ote;
    prp_msg.bit_name.ut = master_data_reg.total_prp_msg.bit.utc|master_data_reg.total_prp_msg.bit.utd|master_data_reg.total_prp_msg.bit.ute;
    prp_msg.bit_name.vdiff = master_data_reg.total_prp_msg.bit.vdiff;
    prp_msg.bit_name.sys_err = master_data_reg.total_prp_msg.bit.fcmos|master_data_reg.total_prp_msg.bit.fdmos;
	
	return prp_msg.data;    
}
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
